package com.mask.im.business.strategy.impl.register;

import cn.hutool.core.lang.Validator;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.mask.im.business.model.entity.UserAuth;
import com.mask.im.business.model.entity.UserInfo;
import com.mask.im.business.model.entity.UserRole;
import com.mask.im.business.enums.SignUpNoticeEnum;
import com.mask.im.business.common.exception.BusinessException;
import com.mask.im.business.mapper.UserAuthMapper;
import com.mask.im.business.mapper.UserInfoMapper;
import com.mask.im.business.mapper.UserRoleMapper;
import com.mask.im.business.model.vo.RegisterVO;
import com.mask.im.business.service.RedisService;
import com.mask.im.business.strategy.RegisterStrategy;
import com.mask.im.business.common.util.CommonUtil;
import com.mask.im.business.common.util.IpUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.transaction.support.TransactionTemplate;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.Objects;

import static com.mask.im.business.common.constant.RedisConstant.EMAIL_REGISTER;
import static com.mask.im.business.common.constant.RegisterConstant.*;
import static com.mask.im.business.common.constant.RegisterConstant.DEFAULT_ROLE;


@Service("emailRegisterImpl")
public class EmailRegisterImpl implements RegisterStrategy {

	@Autowired
	private RedisService redisService;

	@Autowired
	private UserAuthMapper userAuthMapper;

	@Autowired
	private UserInfoMapper userInfoMapper;

	@Autowired
	private PasswordEncoder passwordEncoder;

	@Autowired
	private HttpServletRequest request;

	@Autowired
	private UserRoleMapper userRoleMapper;

	@Autowired
	private TransactionTemplate transactionTemplate;

	@Autowired
	private CommonUtil commonUtil;


	@Override
	public void register(RegisterVO registerVO) {
		verify(registerVO);
		Integer count = userAuthMapper.selectCount(new LambdaQueryWrapper<UserAuth>()
				.eq(UserAuth::getEmail, registerVO.getEmail()));
		if (count > 0) {
			throw new BusinessException("邮箱已经注册或被其他账号绑定");
		}
		String ipAddress = IpUtil.getIpAddress(request);
		String ipSource = IpUtil.getIpSource(ipAddress);

		transactionTemplate.execute(transactionStatus -> {
			//为null说明没有注册有该手机号，则进行默认属性填充
			//保存用户基本信息
			try {
				UserInfo userInfo = UserInfo.builder()
						.username(registerVO.getUsername())
						.avatar(DEFAULT_AVATAR)
						.nickName("用户" + System.currentTimeMillis())
						.gender(DEFAULT_GENDER)
						.disable(DEFAULT_DISABLE).build();
				userInfoMapper.insert(userInfo);
				//保存用户账户信息
				UserAuth auth = UserAuth.builder()
						.userInfoId(userInfo.getId())
						.email(registerVO.getEmail())
						.password(registerVO.getPassword()!=null?passwordEncoder.encode(registerVO.getPassword()):passwordEncoder.encode(DEFAULT_PASSWORD))
						.lastLoginTime(new Date())
						.username(registerVO.getUsername())
						.loginType(EMAIL_TYPE)
						.ipAddress(ipAddress)
						.ipSource(ipSource).build();
				userAuthMapper.insert(auth);
				//保存用户角色信息
				UserRole userRole = UserRole.builder()
						.userInfoId(userInfo.getId())
						.roleId(DEFAULT_ROLE).build();
				userRoleMapper.insert(userRole);
				commonUtil.signUpNotifications(userInfo.getUsername(), SignUpNoticeEnum.getSignUpNoticeType(EMAIL_TYPE));
				return true;
			}catch (Exception e){
				//手动开启事务回滚
				TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
				e.printStackTrace();
				return false;
			}
		});
		redisService.del(EMAIL_REGISTER+registerVO.getEmail());
	}


	/**
	 * 校验
	 *
	 * @param registerVO
	 */
	public void verify(RegisterVO registerVO) {
		if (!Validator.isEmail(registerVO.getEmail())) {
			throw new BusinessException("邮箱格式错误");
		}
		if (registerVO.getPassword().isEmpty()){
			throw new BusinessException("密码不能为空");
		}
		String code = (String) redisService.get(EMAIL_REGISTER + registerVO.getEmail());
		if (Objects.isNull(code)) {
			throw new BusinessException("验证码已过期");
		}
		if (registerVO.getCode() == null || !code.equals(registerVO.getCode())) {
			throw new BusinessException("验证码不正确");
		}
		if (!registerVO.getPassword().equals(registerVO.getConfirmPassword())){
			throw new BusinessException("两次密码输入不一致");
		}
	}
}
